<template>
    <el-upload
        :action="action"
        :auto-upload="autoUpload"
        v-bind="$attrs"
        :limit="limit"
        :accept="accept"
        :multiple="multiple"
        :file-list="formData[$attrs.prop]"
        :on-success="doSuccess"
        :on-remove="doRemove"
        :on-preview="doPreview"
        :on-exceed="doExceed"
        :on-error="doError"
        :on-progress="doProgress"
        :on-change="doChange"
        :before-upload="doBeforeUpload"
        :before-remove="doBeforeRemove"
    >
        <template #trigger>
            <MetaIcon v-if="$attrs.icon" name="UploadFilled"></MetaIcon>
            <el-button
                v-else
                size="small"
                :type="btnType"
                plain
                :disabled="$attrs.disabled"
                ><MetaIcon name="UploadFilled"></MetaIcon
                ><span>{{ btnText || '选取文件' }}</span></el-button
            >
        </template>
        <template #tip>
            <div
                class="el-upload__tip"
                style="color: red; line-height: 16px"
                :style="!tip || !tip.trim() ? 'margin-top: 0' : ''"
            >
                {{
                    tip
                        ? tip
                        : '最多上传' + limit + '个20Mb以内文件(' + accept + ')'
                }}
            </div>
        </template>
    </el-upload>
</template>

<script>
// 上传、删除、预览、超出
import { Viewer } from 'v-viewer'
import MetaIcon from '@/components/MetaIcon/index.vue'
import { doUploadFileData, getFileExtName, getFileName } from '@/utils'
import { api as viewerApi } from 'v-viewer'
import { computed, ref } from 'vue'
import { ElMessage } from 'element-plus'
import { useLoadingStore } from '@/stores/loading'
export default {
    components: {
        Viewer
    },
    props: {
        formData: {
            type: Object,
            default: () => ({})
        },
        action: {
            type: String,
            default: '#'
        },
        limit: {
            type: [Number, null, undefined],
            default: 5
        },
        autoUpload: {
            type: Boolean,
            default: false
        },
        btnText: {
            type: String,
            default: ''
        },
        btnType: {
            type: String,
            default: 'primary'
        },
        tip: {
            type: String,
            default: ''
        },
        accept: {
            type: String,
            default: '.jpg, .jpeg, .png, .pdf, .doc, .docx, .xls, .xlsx'
        },
        size: {
            type: Number,
            default: 20
        },
        multiple: {
            type: Boolean,
            default: false
        },
        IsChangeImage: {
            type: Number,
            default: 0
        },
        onSuccess: {
            type: [Function, undefined],
            default: undefined
        },
        onRemove: {
            type: [Function, undefined],
            default: undefined
        },
        onPreview: {
            type: [Function, undefined],
            default: undefined
        },
        onExceed: {
            type: [Function, undefined],
            default: undefined
        },
        onError: {
            type: [Function, undefined],
            default: undefined
        },
        onProgress: {
            type: [Function, undefined],
            default: undefined
        },
        onChange: {
            type: [Function, undefined],
            default: undefined
        },
        beforeUpload: {
            type: [Function, undefined],
            default: undefined
        },
        beforeRemove: {
            type: [Function, undefined],
            default: undefined
        }
    },
    setup(props, context) {
        const loadingStore = useLoadingStore()
        let timer = null
        const imageType = ['jpg', 'jpeg', 'png']
        const imageList = computed(() => {
            return props.formData[context.attrs.prop]
                .filter((i) =>
                    imageType.includes(
                        getFileExtName(getFileName(i.url)).toLowerCase()
                    )
                )
                .map((j) => j.url)
        })
        const doSuccess = (response, file, fileList) => {
            //自定义
            if (props.onSuccess) {
                props.onSuccess(response, file, fileList)
                return
            }
        }
        const doError = (err, file, fileList) => {
            if (props.onError) {
                props.onError(err, file, fileList)
                return
            }
        }
        const doProgress = (event, file, fileList) => {
            if (props.onProgress) {
                props.onProgress(event, file, fileList)
                return
            }
        }

        // 删除文件
        const doRemove = (file, fileList) => {
            //自定义
            if (props.onRemove) {
                props.onRemove(file, fileList)
                return
            }
            const list = JSON.parse(
                JSON.stringify(props.formData[context.attrs.prop])
            )
            props.formData[context.attrs.prop] = list.filter(
                (i) => i.name !== file.name
            )
        }

        // 选择后上传
        const handleFinalChange = (fileList) => {
            // 是否有文件超出限制
            const isSizeLarge = fileList.some(
                (file) => file.size > props.size * 1024 * 1024
            )
            if (isSizeLarge) {
                ElMessage.error('文件大小超出限制，请重新选择')
                return
            }
            loadingStore.showFullLoading = true

            const fileListPromiseList = []

            fileList.forEach((file) => {
                // 上传base64图片
                let p = new Promise((reslove, reject) => {
                    doUploadFileData(file.raw, props.IsChangeImage)
                        .then((res) => {
                            reslove(res)
                        })
                        .catch((e) => {
                            reject(e)
                            console.log(e)
                        })
                })
                fileListPromiseList.push(p)
            })

            Promise.allSettled(fileListPromiseList).then((results) => {
                loadingStore.showFullLoading = false
                const list = JSON.parse(
                    JSON.stringify(props.formData[context.attrs.prop])
                )
                results
                    .filter((item) => item.status === 'fulfilled')
                    .forEach((item) => {
                        let isHave = false
                        list.forEach((i, idx) => {
                            if (i.name === getFileName(item.value.url)) {
                                console.log(22222)
                                isHave = true
                                list.splice(idx, 1, {
                                    name: getFileName(item.value.url),
                                    url: item.value.url
                                })
                            }
                        })
                        if (!isHave) {
                            list.push({
                                name: getFileName(item.value.url),
                                url: item.value.url
                            })
                        }
                    })
                props.formData[context.attrs.prop] = list
            })
        }

        // 上传文件
        const doChange = (file, fileList) => {
            if (props.onChange) {
                props.onChange(file, fileList)
                return
            }
            if (timer) {
                clearTimeout(timer)
            }

            timer = setTimeout(() => {
                // 拿到最终的list开始上传服务器，base64获取网络链接
                handleFinalChange(fileList)
            }, 500)
        }

        const doPreview = (file) => {
            //自定义
            if (props.onPreview) {
                props.onPreview(file)
                return
            }
            const list = JSON.parse(
                JSON.stringify(props.formData[context.attrs.prop])
            )
            const previewData =
                list.filter((i) => i.name === file.name)[0] || {}

            if (
                imageType.includes(
                    getFileExtName(getFileName(previewData.url)).toLowerCase()
                )
            ) {
                viewerApi({
                    images: imageList.value,
                    options: {
                        initialViewIndex: imageList.value.indexOf(
                            previewData.url
                        )
                    }
                })
            } else {
                if (previewData && previewData.url) {
                    window.open(file.url, '_blank')
                }
            }
        }
        // 上传超出限制，删除第一个，补一个
        const doExceed = (files, fileList) => {
            ElMessage.error(`上传文件数量超出限制，无法上传`)
            // if (props.onExceed) {
            //     props.onExceed(files, fileList)
            //     return
            // }
            // if (files[0].size > props.size * 1024) {
            //     ElMessage.error('文件大小超出限制，请重新选择')
            //     return
            // }
            // 上传base64图片
            // doUploadFileData(files[0])
            //     .then((res) => {
            //         // 替换整个数组，不然有可能监听不到响应式
            //         const list = JSON.parse(
            //             JSON.stringify(props.formData[context.attrs.prop])
            //         )
            //         let isHave = false
            //         list.forEach((i, idx) => {
            //             if (i.name === getFileName(res.url)) {
            //                 isHave = true
            //                 list.splice(idx, 1, {
            //                     name: getFileName(res.url),
            //                     url: res.url
            //                 })
            //             }
            //         })
            //         if (!isHave) {
            //             list.splice(0, 1, {
            //                 name: getFileName(res.url),
            //                 url: res.url
            //             })
            //         }

            //         props.formData[context.attrs.prop] = list
            //     })
            //     .catch((e) => {
            //         console.log(e)
            //     })
        }
        const doBeforeUpload = (file) => {
            if (props.beforeUpload) {
                props.beforeUpload(file)
                return
            }
        }
        const doBeforeRemove = (file, fileList) => {
            if (props.beforeRemove) {
                props.beforeRemove(file, fileList)
                return
            }
        }

        return {
            doSuccess,
            doError,
            doProgress,
            doRemove,
            doChange,
            doPreview,
            doExceed,
            doBeforeUpload,
            doBeforeRemove
        }
    }
}
</script>

<style></style>
